package com.yue.rpc.remoting.transport.netty.server;

import com.yue.rpc.remoting.dto.RpcMessage;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;

/**
 * @description:
 * @author: zhangqiyue
 * @date: 2023/3/6 16:11
 **/
public class NettyServer {
    private static final String IP = "127.0.0.1";
    private static final int PORT = 9999;
    static final int BIZGROUPSIZE = Runtime.getRuntime().availableProcessors() * 2;
    static final int BIZTHREADSIZE = 4;

    private static final EventLoopGroup bossGroup = new NioEventLoopGroup(BIZGROUPSIZE);
    private static final EventLoopGroup workerGroup = new NioEventLoopGroup(BIZTHREADSIZE);

    protected static void run(final NettyServerListener listener) throws Exception {
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup);
        b.channel(NioServerSocketChannel.class);
        b.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
                pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
                pipeline.addLast("decoder", new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));
                pipeline.addLast("encoder", new ObjectEncoder());
                pipeline.addLast(new NettyServerHandler(listener));
            }
        });

        b.bind(IP, PORT).sync();
        System.out.println("TCP服务器已启动");
    }

    protected static void shutdown() {
        workerGroup.shutdownGracefully();
        bossGroup.shutdownGracefully();
    }

    public static void main(String[] args) throws Exception {
        System.out.println("开始启动TCP服务器...");
        NettyServer.run(new NettyServerListener() {
            @Override
            public void channelRead(ChannelHandlerContext ctx, RpcMessage message) {
                try {
                    String serviceCode = message.getServiceCode();
                    //业务分发
                    switch (serviceCode) {
                        case "add_user":
                            break;
                        case "update_user":
                            break;
                        case "print_user":
                            String userName = new String(message.getValue(), "UTF-8");
                            System.out.println(userName);
                            userName = "Hello " + userName + " !";
                            message.setValue(userName.getBytes("UTF-8"));
                            //返回处理结果
                            ctx.channel().writeAndFlush(message).sync();
                            break;
                        default:
                            message.setValue("{error}".getBytes("UTF-8"));
                            ctx.channel().writeAndFlush(message).sync();
                            break;
                    }
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        });
//      TcpServer.shutdown();
    }
}